package com.nbcb.fund.common.aop;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;


/**
 * 日志aop
 *
 * @author 九分石人
 */
@Slf4j
@Order(1)
@Aspect
@Component
public class LogAspect {

    @Resource
    ObjectMapper objectMapper;


    @Pointcut("execution(public * com.nbcb.fund.web..*.*(..))")
    public void log() {
    }

    @Around("log()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();

        long startTime = System.currentTimeMillis();
        Object result;

        try {
            result = pjp.proceed();
        } catch (Throwable throwable) {
            log.error("接口入参,[{}] -> [{}] costs:{}ms -> req:{},error:{}",
                    request.getMethod(),
                    request.getServletPath(),
                    System.currentTimeMillis() - startTime,
                    getArgsJson(pjp.getArgs()),
                    throwable.getMessage()
            );
            throw throwable;
        }
        log.info("接口入参,[{}] -> [{}] costs:{}ms -> req:{},resp:{}",
                request.getMethod(),
                request.getServletPath(),
                System.currentTimeMillis() - startTime,
                getArgsJson(pjp.getArgs()),
                objectMapper.writeValueAsString(result)
        );
        return result;
    }

    private String getArgsJson(Object[] args) {
        try {
            return objectMapper.writeValueAsString(args);
        } catch (Exception e) {
            return "args to json error";
        }
    }

}
